package net.oschina.allchat.message.processing;

import java.math.BigDecimal;
import java.math.BigInteger;

import net.oschina.allchat.message.processing.conversion.ConversionException;

public final class Attribute<T> {
	public enum Type {
		STRING,
		INT,
		LONG,
		FLOAT,
		DOUBLE,
		BIG_INT,
		DECIMAL,
		BOOLEAN
	}
	
	private String prefix;
	private String localName;
	private T value;
	private Type type;
	
	private Attribute(String prefix, String localName, T value, Type type) {
		this.prefix = prefix;
		this.localName = localName;
		this.value = value;
		this.type = type;
	}
	
	public String getPrefix() {
		return prefix;
	}
	
	public void setPrefix(String prefix) {
		this.prefix = prefix;
	}
	
	public String getLocalName() {
		return localName;
	}
	
	public void setLocalName(String localName) {
		this.localName = localName;
	}
	
	public T getValue() {
		return value;
	}
	
	public void setValue(T value) {
		this.value = value;
	}
	
	public Attribute.Type getType() {
		return type;
	}
	
	public static Attribute<String> createStringAttribute(String prefix, String localName, String value) {
		return new Attribute<String>(prefix, localName, value, Type.STRING);
	}
	
	public static Attribute<Integer> createIntAttribute(String prefix, String localName, Integer value) {
		return new Attribute<Integer>(prefix, localName, value, Type.INT);
	}
	
	public static Attribute<Long> createLongAttribute(String prefix, String localName, Long value) {
		return new Attribute<Long>(prefix, localName, value, Type.LONG);
	}
	
	public static Attribute<BigInteger> createBigIntAttribute(String prefix, String localName, BigInteger value) {
		return new Attribute<BigInteger>(prefix, localName, value, Type.BIG_INT);
	}
	
	public static Attribute<Float> createFloatAttribute(String prefix, String localName, Float value) {
		return new Attribute<Float>(prefix, localName, value, Type.FLOAT);
	}
	
	public static Attribute<Double> createDoubleAttribute(String prefix, String localName, Double value) {
		return new Attribute<Double>(prefix, localName, value, Type.DOUBLE);
	}
	
	public static Attribute<BigDecimal> createDecimalAttribute(String prefix, String localName, BigDecimal value) {
		return new Attribute<BigDecimal>(prefix, localName, value, Type.DECIMAL);
	}
	
	public static Attribute<Boolean> createBooleanAttribute(String prefix, String localName, Boolean value) {
		return new Attribute<Boolean>(prefix, localName, value, Type.BOOLEAN);
	}
	
	@SuppressWarnings("unchecked")
	public Attribute<String> stringIt() throws ConversionException {
		if (type == Type.STRING)
			return (Attribute<String>)this;
		
		throw new ConversionException(String.format("is %s", type));
	}
	
	@SuppressWarnings("unchecked")
	public Attribute<Integer> intIt() throws ConversionException {
		if (type == Type.INT)
			return (Attribute<Integer>)this;
		
		throw new ConversionException(String.format("is %s", type));
	}
	
	@SuppressWarnings("unchecked")
	public Attribute<Long> longIt() throws ConversionException {
		if (type == Type.LONG)
			return (Attribute<Long>)this;
		
		throw new ConversionException(String.format("is %s", type));
	}
	
	@SuppressWarnings("unchecked")
	public Attribute<BigInteger> bigIntIt() throws ConversionException {
		if (type == Type.BIG_INT)
			return (Attribute<BigInteger>)this;
		
		throw new ConversionException(String.format("is %s", type));
	}
	
	@SuppressWarnings("unchecked")
	public Attribute<Float> floatIt() throws ConversionException {
		if (type == Type.FLOAT)
			return (Attribute<Float>)this;
		
		throw new ConversionException(String.format("is %s", type));
	}
	
	@SuppressWarnings("unchecked")
	public Attribute<Double> doubleIt() throws ConversionException {
		if (type == Type.DOUBLE)
			return (Attribute<Double>)this;
		
		throw new ConversionException(String.format("is %s", type));
	}
	
	@SuppressWarnings("unchecked")
	public Attribute<BigDecimal> decimalIt() throws ConversionException {
		if (type == Type.DECIMAL)
			return (Attribute<BigDecimal>)this;
		
		throw new ConversionException(String.format("is %s", type));
	}
	
	@SuppressWarnings("unchecked")
	public Attribute<Boolean> booleanIt() throws ConversionException {
		if (type == Type.BOOLEAN)
			return (Attribute<Boolean>)this;
		
		throw new ConversionException(String.format("is %s", type));
	}
	
	public String stringValue() {
		try {
			return stringIt().getValue();
		} catch (ConversionException e) {
			throw new BadMessageException("value should be string tye", e);
		}
	}
	
	public int intValue() {
		try {
			return intIt().getValue();
		} catch (ConversionException e) {
			throw new BadMessageException("value should be int tye", e);
		}
	}
	
	public long longValue() {
		try {
			return longIt().getValue();
		} catch (ConversionException e) {
			throw new BadMessageException("value should be long tye", e);
		}
	}
	
	public BigInteger bigIntValue() {
		try {
			return bigIntIt().getValue();
		} catch (ConversionException e) {
			throw new BadMessageException("value should be BigInteger tye", e);
		}
	}
	
	public float floatValue() {
		try {
			return floatIt().getValue();
		} catch (ConversionException e) {
			throw new BadMessageException("value should be float tye", e);
		}
	}
	
	public double doubleValue() {
		try {
			return doubleIt().getValue();
		} catch (ConversionException e) {
			throw new BadMessageException("value should be double tye", e);
		}
	}
	
	public BigDecimal decimalValue() {
		try {
			return decimalIt().getValue();
		} catch (ConversionException e) {
			throw new BadMessageException("value should be BigDecimal tye", e);
		}
	}
	
	public boolean booleanValue() {
		try {
			return booleanIt().getValue();
		} catch (ConversionException e) {
			throw new BadMessageException("value should be boolean tye", e);
		}
	}
}
